home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 1995 #5 & #6 / Amiga Plus CD - 1995 - No. 5 and 6.iso / pd / netz / term / extras / source / term-source.lha / termSaveWindow.c < prev    next >
C/C++ Source or Header  |  1995-06-17  |  19KB  |  948 lines

  1. /*
  2. **    termSaveWindow.c
  3. **
  4. **    Support routines for saving IFF-ILBM files
  5. **
  6. **    Copyright © 1990-1995 by Olaf `Olsen' Barthel
  7. **        All Rights Reserved
  8. */
  9.  
  10. #include "termGlobal.h"
  11.  
  12.     /* Current compression mode. */
  13.  
  14. #define DUMP        0
  15. #define RUN        1
  16.  
  17.     /* ByteRun compression data. */
  18.  
  19. #define MINRUN        3
  20. #define MAXRUN        128
  21. #define MAXDAT        128
  22.  
  23.     /* Chunk types. */
  24.  
  25. #define ID_ILBM        MAKE_ID('I','L','B','M')
  26. #define ID_ANNO        MAKE_ID('A','N','N','O')
  27. #define ID_BMHD        MAKE_ID('B','M','H','D')
  28. #define ID_CMAP        MAKE_ID('C','M','A','P')
  29. #define ID_CAMG        MAKE_ID('C','A','M','G')
  30. #define ID_BODY        MAKE_ID('B','O','D','Y')
  31.  
  32.     /* Masking technique. */
  33.  
  34. #define mskNone        0
  35.  
  36.     /* Compression techniques. */
  37.  
  38. #define cmpNone        0
  39. #define cmpByteRun1    1
  40.  
  41.     /* A bitmap header. */
  42.  
  43. typedef struct
  44. {
  45.     UWORD        w,h;            /* raster width & height in pixels */
  46.     WORD        x,y;            /* position for this image */
  47.     UBYTE        nPlanes;        /* # source bitplanes */
  48.     UBYTE        masking;        /* masking technique */
  49.     UBYTE        compression;        /* compression algorithm */
  50.     UBYTE        pad1;            /* UNUSED.  For consistency, put 0 here.*/
  51.     UWORD        transparentColor;    /* transparent "color number" */
  52.     UBYTE        xAspect,yAspect;    /* aspect ratio, a rational number x/y */
  53.     WORD        pageWidth,pageHeight;    /* source "page" size in pixels */
  54. } BitMapHeader;
  55.  
  56.     /* A single 8-bit colour register. */
  57.  
  58. typedef struct
  59. {
  60.     UBYTE        red,            /* red component, 0..255 */
  61.             green,            /* green component, 0..255 */
  62.             blue;            /* blue component, 0..255 */
  63. } ColorRegister;
  64.  
  65.     /* Local packer data. */
  66.  
  67. STATIC LONG        PackedBytes;
  68. STATIC BYTE        Buffer[MAXDAT + 1];
  69.  
  70.     /* PutDump(register PLANEPTR Destination,register LONG Count):
  71.      *
  72.      *    Output a byte dump.
  73.      */
  74.  
  75. STATIC PLANEPTR __regargs
  76. PutDump(register PLANEPTR Destination,register LONG Count)
  77. {
  78.     register PLANEPTR Source = Buffer;
  79.  
  80.     *Destination++     = Count - 1;
  81.      PackedBytes    += Count + 1;
  82.  
  83.     while(Count--)
  84.         *Destination++ = *Source++;
  85.  
  86.     return(Destination);
  87. }
  88.  
  89.     /* PutRun(register PLANEPTR Destination,LONG Count,WORD Char):
  90.      *
  91.      *    Output a byte run.
  92.      */
  93.  
  94. STATIC PLANEPTR __regargs
  95. PutRun(register PLANEPTR Destination,LONG Count,WORD Char)
  96. {
  97.     *Destination++     = -(Count - 1);
  98.     *Destination++     = Char;
  99.      PackedBytes    += 2;
  100.  
  101.     return(Destination);
  102. }
  103.  
  104.     /* PackRow(PLANEPTR *SourcePtr,register PLANEPTR Destination,LONG RowSize):
  105.      *
  106.      *    Pack a row of bitmap data using ByteRun compression,
  107.      *    based on the original "EA IFF 85" pack.c example code.
  108.      */
  109.  
  110. STATIC LONG __regargs
  111. PackRow(PLANEPTR *SourcePtr,register PLANEPTR Destination,LONG RowSize)
  112. {
  113.     register PLANEPTR Source = *SourcePtr;
  114.  
  115.     WORD    Buffered    = 1,
  116.         RunStart    = 0;
  117.     BYTE    Mode        = DUMP,
  118.         LastChar,
  119.         Char;
  120.  
  121.     PackedBytes = 0;
  122.  
  123.     Buffer[0] = LastChar = Char = *Source++;
  124.  
  125.     RowSize--;
  126.  
  127.     while(RowSize--)
  128.     {
  129.         Buffer[Buffered++] = Char = *Source++;
  130.  
  131.         if(Mode)
  132.         {
  133.             if((Char != LastChar) || (Buffered - RunStart > MAXRUN))
  134.             {
  135.                 Destination    = PutRun(Destination,Buffered - 1 - RunStart,LastChar);
  136.                 Buffer[0]    = Char;
  137.                 Buffered    = 1;
  138.                 RunStart    = 0;
  139.                 Mode        = DUMP;
  140.             }
  141.         }
  142.         else
  143.         {
  144.             if(Buffered > MAXDAT)
  145.             {
  146.                 Destination    = PutDump(Destination,Buffered - 1);
  147.                 Buffer[0]    = Char;
  148.                 Buffered    = 1;
  149.                 RunStart    = 0;
  150.             }
  151.             else
  152.             {
  153.                 if(Char == LastChar)
  154.                 {
  155.                     if(Buffered - RunStart >= MINRUN)
  156.                     {
  157.                         if(RunStart)
  158.                             Destination = PutDump(Destination,RunStart);
  159.  
  160.                         Mode = RUN;
  161.                     }
  162.                     else
  163.                     {
  164.                         if(!RunStart)
  165.                             Mode = RUN;
  166.                     }
  167.                 }
  168.                 else
  169.                     RunStart = Buffered - 1;
  170.             }
  171.         }
  172.  
  173.         LastChar = Char;
  174.     }
  175.  
  176.     if(Mode)
  177.         PutRun(Destination,Buffered - RunStart,LastChar);
  178.     else
  179.         PutDump(Destination,Buffered);
  180.  
  181.     *SourcePtr = Source;
  182.  
  183.     return(PackedBytes);
  184. }
  185.  
  186.     /* PutANNO(struct IFFHandle *Handle):
  187.      *
  188.      *    Output `ANNO' chunk.
  189.      */
  190.  
  191. STATIC BYTE __regargs
  192. PutANNO(struct IFFHandle *Handle)
  193. {
  194.     extern    UBYTE __far    VersTag[];
  195.         WORD        Len;
  196.  
  197.     LONG    Error;
  198.  
  199.     Len = strlen(&VersTag[1]);
  200.  
  201.         /* Push the `ANNO' chunk on the stack. */
  202.  
  203.     if(!(Error = PushChunk(Handle,0,ID_ANNO,Len)))
  204.     {
  205.             /* Write the creator string. */
  206.  
  207.         if(WriteChunkBytes(Handle,&VersTag[1],Len) == Len)
  208.         {
  209.                 /* Pop the `ANNO' chunk. */
  210.  
  211.             if(!(Error = PopChunk(Handle)))
  212.                 return(TRUE);
  213.         }
  214.         else
  215.             Error = IoErr();
  216.     }
  217.  
  218.     SetIoErr(Error);
  219.  
  220.     return(FALSE);
  221. }
  222.  
  223.     /* PutBMHD():
  224.      *
  225.      *    Output `BMHD' chunk.
  226.      */
  227.  
  228. STATIC BYTE __regargs
  229. PutBMHD(struct IFFHandle *Handle,struct Window *Window,UBYTE Compression,LONG Left,LONG Top,LONG Width,LONG Height)
  230. {
  231.     struct DisplayInfo    DisplayInfo;
  232.     LONG            Error = 0;
  233.  
  234.         /* Get the display aspect ratio. */
  235.  
  236.     if(GetDisplayInfoData(NULL,(APTR)&DisplayInfo,sizeof(struct DisplayInfo),DTAG_DISP,GetVPModeID(&Window -> WScreen -> ViewPort)))
  237.     {
  238.         BitMapHeader Header;
  239.  
  240.             /* Fill in the bitmap header. */
  241.  
  242.         Header . w            = Width;
  243.         Header . h            = Height;
  244.         Header . pageWidth        = Window -> WScreen -> Width;
  245.         Header . pageHeight        = Window -> WScreen -> Height;
  246.         Header . x            = Left;
  247.         Header . y            = Top;
  248.         Header . nPlanes        = GetBitMapDepth(Window -> WScreen -> RastPort . BitMap);
  249.         Header . masking        = mskNone;
  250.         Header . compression        = Compression;
  251.         Header . pad1            = 0;
  252.         Header . transparentColor    = 0;
  253.         Header . xAspect        = DisplayInfo . Resolution . x;
  254.         Header . yAspect        = DisplayInfo . Resolution . y;
  255.  
  256.             /* Push the `BMHD' chunk on the stack. */
  257.  
  258.         if(!(Error = PushChunk(Handle,0,ID_BMHD,sizeof(BitMapHeader))))
  259.         {
  260.                 /* Write the bitmap header. */
  261.  
  262.             if(WriteChunkBytes(Handle,&Header,sizeof(BitMapHeader)) == sizeof(BitMapHeader))
  263.             {
  264.                     /* Pop the `BMHD' chunk. */
  265.  
  266.                 if(!(Error = PopChunk(Handle)))
  267.                     return(TRUE);
  268.             }
  269.             else
  270.                 Error = IoErr();
  271.         }
  272.     }
  273.     else
  274.         Error = ERR_NO_MEM;
  275.  
  276.     if(Error)
  277.         SetIoErr(Error);
  278.  
  279.     return(FALSE);
  280. }
  281.  
  282.     /* PutCMAP(struct IFFHandle *Handle,struct ViewPort *VPort):
  283.      *
  284.      *    Output `CMAP' chunk, only 4-bit colour registers
  285.      *    are supported so far.
  286.      */
  287.  
  288. STATIC BYTE __regargs
  289. PutCMAP(struct IFFHandle *Handle,struct ViewPort *VPort)
  290. {
  291.     LONG Error;
  292.  
  293.         /* Push the `CMAP' chunk on the stack. */
  294.  
  295.     if(!(Error = PushChunk(Handle,0,ID_CMAP,3 * VPort -> ColorMap -> Count)))
  296.     {
  297.         ColorRegister    Colour;
  298.         LONG        i;
  299.         ULONG        Value,
  300.                 R,G,B;
  301.  
  302.             /* Read and convert all the
  303.              * ColorMap entries (4 bit colour
  304.              * components only).
  305.              */
  306.  
  307.         if(Kick30)
  308.         {
  309.             ULONG RGB[3];
  310.  
  311.             for(i = 0 ; i < VPort -> ColorMap -> Count ; i++)
  312.             {
  313.                     /* Read colour value. */
  314.  
  315.                 GetRGB32(VPort -> ColorMap,i,1,RGB);
  316.  
  317.                     /* Store the colour components. */
  318.  
  319.                 Colour . red    = RGB[0] >> 24;
  320.                 Colour . green    = RGB[1] >> 24;
  321.                 Colour . blue    = RGB[2] >> 24;
  322.  
  323.                     /* Write the colours. */
  324.  
  325.                 if(WriteChunkBytes(Handle,&Colour,3) != 3)
  326.                     return(FALSE);
  327.             }
  328.         }
  329.         else
  330.         {
  331.             for(i = 0 ; i < VPort -> ColorMap -> Count ; i++)
  332.             {
  333.                     /* Read colour value. */
  334.  
  335.                 Value = GetRGB4(VPort -> ColorMap,i);
  336.  
  337.                     /* Split the value into components. */
  338.  
  339.                 R = (Value >> 8) & 0xF;
  340.                 G = (Value >> 4) & 0xF;
  341.                 B = (Value     ) & 0xF;
  342.  
  343.                     /* Store the colour components. */
  344.  
  345.                 Colour . red    = (R << 4) | R;
  346.                 Colour . green    = (G << 4) | G;
  347.                 Colour . blue    = (B << 4) | B;
  348.  
  349.                     /* Write the colours. */
  350.  
  351.                 if(WriteChunkBytes(Handle,&Colour,3) != 3)
  352.                     return(FALSE);
  353.             }
  354.         }
  355.  
  356.             /* Pop the `CMAP' chunk. */
  357.  
  358.         if(!(Error = PopChunk(Handle)))
  359.             return(TRUE);
  360.     }
  361.  
  362.     SetIoErr(Error);
  363.  
  364.     return(FALSE);
  365. }
  366.  
  367.     /* PutCAMG(struct IFFHandle *Handle,struct ViewPort *VPort):
  368.      *
  369.      *    Output `CAMG' chunk.
  370.      */
  371.  
  372. STATIC BYTE __regargs
  373. PutCAMG(struct IFFHandle *Handle,struct ViewPort *VPort)
  374. {
  375.     LONG Error;
  376.  
  377.     if(!(Error = PushChunk(Handle,0,ID_CAMG,sizeof(ULONG))))
  378.     {
  379.         ULONG ViewModes = GetVPModeID(VPort);
  380.  
  381.         if(WriteChunkBytes(Handle,&ViewModes,sizeof(ULONG)) == sizeof(ULONG))
  382.         {
  383.             if(!(Error = PopChunk(Handle)))
  384.                 return(TRUE);
  385.         }
  386.         else
  387.             Error = IoErr();
  388.     }
  389.  
  390.     if(Error)
  391.         SetIoErr(Error);
  392.  
  393.     return(FALSE);
  394. }
  395.  
  396.     /* PutBODY(struct IFFHandle *Handle)
  397.      *
  398.      *    Output `BODY' chunk.
  399.      */
  400.  
  401. STATIC BYTE __regargs
  402. PutBODY(struct IFFHandle *Handle,struct BitMap *BitMap,UBYTE Compression)
  403. {
  404.     BYTE         Success = FALSE;
  405.     PLANEPTR    *Planes;
  406.     LONG         Error = 0;
  407.  
  408.         /* Allocate temporary bitplane pointers. */
  409.  
  410.     if(Planes = (PLANEPTR *)AllocVecPooled(BitMap -> Depth * sizeof(PLANEPTR *),MEMF_ANY | MEMF_CLEAR))
  411.     {
  412.         register LONG i;
  413.  
  414.             /* Copy the bitplane pointers. */
  415.  
  416.         for(i = 0 ; i < BitMap -> Depth ; i++)
  417.             Planes[i] = BitMap -> Planes[i];
  418.  
  419.             /* Are we to compress the data? */
  420.  
  421.         if(Compression == cmpByteRun1)
  422.         {
  423.             PLANEPTR PackBuffer;
  424.  
  425.                 /* Allocate line compression buffer. */
  426.  
  427.             if(PackBuffer = (PLANEPTR)AllocVecPooled(BitMap -> BytesPerRow * 2,MEMF_ANY))
  428.             {
  429.                     /* Push the `BODY' chunk on the stack. */
  430.  
  431.                 if(!(Error = PushChunk(Handle,0,ID_BODY,IFFSIZE_UNKNOWN)))
  432.                 {
  433.                     register LONG    PackedBytes,
  434.                             j;
  435.  
  436.                         /* So far, we are quite successful,
  437.                          * any write access to fail will
  438.                          * cause `Success' to drop to FALSE.
  439.                          */
  440.  
  441.                     Success = TRUE;
  442.  
  443.                         /* Compress all the rows. */
  444.  
  445.                     for(i = 0 ; Success && i < BitMap -> Rows ; i++)
  446.                     {
  447.                             /* Compress all the planes. */
  448.  
  449.                         for(j = 0 ; Success && j < BitMap -> Depth ; j++)
  450.                         {
  451.                                 /* Do the compression. */
  452.  
  453.                             PackedBytes = PackRow(&Planes[j],PackBuffer,BitMap -> BytesPerRow);
  454.  
  455.                                 /* Write the compressed data. */
  456.  
  457.                             if(WriteChunkBytes(Handle,PackBuffer,PackedBytes) != PackedBytes)
  458.                             {
  459.                                 Error = IoErr();
  460.  
  461.                                 Success = FALSE;
  462.                             }
  463.                         }
  464.                     }
  465.  
  466.                         /* Pop the `BODY' chunk. */
  467.  
  468.                     if(Success)
  469.                     {
  470.                         if(Error = PopChunk(Handle))
  471.                             Success = FALSE;
  472.                     }
  473.                 }
  474.  
  475.                     /* Free the line compression buffer. */
  476.  
  477.                 FreeVecPooled(PackBuffer);
  478.             }
  479.             else
  480.                 Error = ERR_NO_MEM;
  481.         }
  482.         else
  483.         {
  484.                 /* Push the `BODY' chunk on the stack. */
  485.  
  486.             if(!(Error = PushChunk(Handle,0,ID_BODY,IFFSIZE_UNKNOWN)))
  487.             {
  488.                 register LONG j;
  489.  
  490.                     /* So far, we are quite successful,
  491.                      * any write access to fail will
  492.                      * cause `Success' to drop to FALSE.
  493.                      */
  494.  
  495.                 Success = TRUE;
  496.  
  497.                     /* Compress all the rows. */
  498.  
  499.                 for(i = 0 ; Success && i < BitMap -> Rows ; i++)
  500.                 {
  501.                         /* Compress all the planes. */
  502.  
  503.                     for(j = 0 ; Success && j < BitMap -> Depth ; j++)
  504.                     {
  505.                             /* Write the row. */
  506.  
  507.                         if(WriteChunkBytes(Handle,Planes[j],BitMap -> BytesPerRow) != BitMap -> BytesPerRow)
  508.                         {
  509.                             Error = IoErr();
  510.  
  511.                             Success = FALSE;
  512.                         }
  513.                         else
  514.                             Planes[j] += BitMap -> BytesPerRow;
  515.                     }
  516.                 }
  517.  
  518.                     /* Pop the `BODY' chunk. */
  519.  
  520.                 if(Success)
  521.                 {
  522.                     if(Error = PopChunk(Handle))
  523.                         Success = FALSE;
  524.                 }
  525.             }
  526.         }
  527.  
  528.             /* Free the temporary bitplane pointers. */
  529.  
  530.         FreeVecPooled(Planes);
  531.     }
  532.     else
  533.         Error = ERR_NO_MEM;
  534.  
  535.     if(Error)
  536.         SetIoErr(Error);
  537.  
  538.         /* Return the result. */
  539.  
  540.     return(Success);
  541. }
  542.  
  543.     /* SaveWindow(STRPTR Name,struct Window *Window):
  544.      *
  545.      *    Save the contents of a window to a file.
  546.      */
  547.  
  548. BYTE __regargs
  549. SaveWindow(STRPTR Name,struct Window *Window)
  550. {
  551.     BYTE    Success    = FALSE,
  552.         NewFile    = FALSE,
  553.         Locked    = TRUE;
  554.     LONG    Error    = 0;
  555.  
  556.     LockLayerRom(Window -> RPort -> Layer);
  557.  
  558.         // Datatypes available?
  559.  
  560.     if(DataTypesBase)
  561.     {
  562.         struct BitMap    *BitMap;
  563.         struct Screen    *Screen = Window -> WScreen;
  564.         LONG         Left,Top,
  565.                  Width,Height;
  566.         Object        *Picture = NULL;
  567.  
  568.             // Keep these handy
  569.  
  570.         Left    = Window -> LeftEdge    + Window -> BorderLeft;
  571.         Top    = Window -> TopEdge    + Window -> BorderTop;
  572.         Width    = Window -> Width    - (Window -> BorderLeft + Window -> BorderRight);
  573.         Height    = Window -> Height    - (Window -> BorderTop + Window -> BorderBottom);
  574.  
  575.         if(!StatusWindow)
  576.             Height -= StatusDisplayHeight;
  577.  
  578.             // This is where the window contents will go
  579.  
  580.         if(BitMap = AllocBitMap(Width,Height,GetBitMapAttr(Window -> RPort -> BitMap,BMA_DEPTH),NULL,Window -> RPort -> BitMap))
  581.         {
  582.             struct RastPort __aligned    RPort;
  583.             LONG                NumColours;
  584.  
  585.                 // Provide temporary storage
  586.  
  587.             InitRastPort(&RPort);
  588.  
  589.             RPort . BitMap = BitMap;
  590.  
  591.                 // Copy the window contents
  592.  
  593.             ClipBlit(Window -> RPort,Window -> BorderLeft,Window -> BorderTop,&RPort,0,0,Width,Height,MINTERM_COPY);
  594.  
  595.                 // Release the layer
  596.  
  597.             UnlockLayerRom(Window -> RPort -> Layer);
  598.  
  599.             Locked = FALSE;
  600.  
  601.                 // Wait until all data is transferred
  602.  
  603.             WaitBlit();
  604.  
  605.                 // Get the number of colours available on this screen
  606.  
  607.             NumColours = Screen -> ViewPort . ColorMap -> Count;
  608.  
  609.                 // Create a picture object
  610.  
  611.             if(Picture = NewDTObject("term image",
  612.                 DTA_SourceType,    DTST_RAM,
  613.                 DTA_GroupID,    GID_PICTURE,
  614.                 PDTA_NumColors,    NumColours,
  615.                 PDTA_BitMap,    BitMap,
  616.                 PDTA_ModeID,    GetVPModeID(&Screen -> ViewPort),
  617.             TAG_DONE))
  618.             {
  619.                 struct ColorRegister    *ColourMap;
  620.                 struct BitMapHeader    *BitMapHeader;
  621.                 ULONG            *Colours;
  622.  
  623.                     // Get the internal data arrays
  624.  
  625.                 if(GetDTAttrs(Picture,
  626.                     PDTA_BitMapHeader,    &BitMapHeader,
  627.                     PDTA_ColorRegisters,    &ColourMap,
  628.                     PDTA_CRegs,        &Colours,
  629.                 TAG_DONE) == 3)
  630.                 {
  631.                     LONG i;
  632.  
  633.                         // Fill in the bitmap header
  634.  
  635.                     BitMapHeader -> bmh_Left    = Left;
  636.                     BitMapHeader -> bmh_Top        = Top;
  637.                     BitMapHeader -> bmh_Width    = Width;
  638.                     BitMapHeader -> bmh_Height    = Height;
  639.                     BitMapHeader -> bmh_Depth    = GetBitMapAttr(BitMap,BMA_DEPTH);
  640.                     BitMapHeader -> bmh_PageWidth    = Screen -> Width;
  641.                     BitMapHeader -> bmh_PageHeight    = Screen -> Height;
  642.  
  643.                         // Get the 32 colours
  644.  
  645.                     GetRGB32(Screen -> ViewPort . ColorMap,0,NumColours,Colours);
  646.  
  647.                         // Get the 24 bit colours
  648.  
  649.                     for(i = 0 ; i < NumColours ; i++)
  650.                     {
  651.                         ColourMap[i] . red    = (UBYTE)(Colours[i * 3 + 0] >> 24);
  652.                         ColourMap[i] . green    = (UBYTE)(Colours[i * 3 + 1] >> 24);
  653.                         ColourMap[i] . blue    = (UBYTE)(Colours[i * 3 + 2] >> 24);
  654.                     }
  655.                 }
  656.                 else
  657.                 {
  658.                     Error = IoErr();
  659.  
  660.                     DisposeDTObject(Picture);
  661.  
  662.                     Picture = NULL;
  663.                 }
  664.             }
  665.             else
  666.                 Error = IoErr();
  667.         }
  668.         else
  669.             Error = ERROR_NO_FREE_STORE;
  670.  
  671.             // Successful so far?
  672.  
  673.         if(Picture)
  674.         {
  675.             BPTR FileHandle;
  676.  
  677.                 // Open the output file
  678.  
  679.             if(FileHandle = Open(Name,MODE_NEWFILE))
  680.             {
  681.                     // Save the image
  682.  
  683.                 if(DoMethod(Picture,DTM_WRITE,NULL,FileHandle,DTWM_IFF,NULL))
  684.                     Success = TRUE;
  685.                 else
  686.                 {
  687.                     Error = IoErr();
  688.  
  689.                     NewFile = TRUE;
  690.                 }
  691.  
  692.                 Close(FileHandle);
  693.             }
  694.             else
  695.                 Error = IoErr();
  696.  
  697.             DisposeDTObject(Picture);
  698.         }
  699.         else
  700.         {
  701.             if(BitMap)
  702.                 FreeBitMap(BitMap);
  703.         }
  704.     }
  705.     else
  706.     {
  707.         struct RastPort    *RPort;
  708.         LONG         Depth;
  709.  
  710.             /* Get the depth. */
  711.  
  712.         Depth = GetBitMapDepth(Window -> WScreen -> RastPort . BitMap);
  713.  
  714.         if(Depth > 8)
  715.         {
  716.             SetIoErr(ERROR_OBJECT_WRONG_TYPE);
  717.  
  718.             return(FALSE);
  719.         }
  720.  
  721.             /* Allocate a dummy rastport, we will need only
  722.              * to copy the contents of the window into the
  723.              * bitmap.
  724.              */
  725.  
  726.         if(RPort = (struct RastPort *)AllocVecPooled(sizeof(struct RastPort),MEMF_ANY))
  727.         {
  728.             struct BitMap *BitMap;
  729.  
  730.                 /* Initialize the rastport with defaults. */
  731.  
  732.             InitRastPort(RPort);
  733.  
  734.                 /* Allocate a bitmap. */
  735.  
  736.             if(BitMap = (struct BitMap *)AllocVecPooled(sizeof(struct BitMap),MEMF_ANY))
  737.             {
  738.                 LONG    Width    = Window -> Width    - (Window -> BorderLeft + Window -> BorderRight),
  739.                     Height    = Window -> Height    - (Window -> BorderTop + Window -> BorderBottom),
  740.                     Left    = Window -> LeftEdge    + Window -> BorderLeft,
  741.                     Top    = Window -> TopEdge    + Window -> BorderTop;
  742.                 WORD    i;
  743.  
  744.                 if(!StatusWindow)
  745.                     Height -= StatusDisplayHeight;
  746.  
  747.                     /* Put it into the rastport. */
  748.  
  749.                 RPort -> BitMap = BitMap;
  750.  
  751.                     /* Initialize it with the window dimensions. */
  752.  
  753.                 InitBitMap(BitMap,Depth,Width,Height);
  754.  
  755.                     /* Flag success so any allocation
  756.                      * to fail in the bitplane allocation
  757.                      * loop will indicate failure.
  758.                      */
  759.  
  760.                 Success = TRUE;
  761.  
  762.                     /* Allocate all the bitplanes necessary. */
  763.  
  764.                 for(i = 0 ; Success && i < BitMap -> Depth ; i++)
  765.                 {
  766.                     if(!(BitMap -> Planes[i] = AllocRaster(Width,Height)))
  767.                         Success = FALSE;
  768.                 }
  769.  
  770.                     /* Did we get all the planes we wanted? */
  771.  
  772.                 if(Success)
  773.                 {
  774.                     struct IFFHandle *Handle;
  775.  
  776.                         /* Copy the window contents to the
  777.                          * local bitmap.
  778.                          */
  779.  
  780.                     ClipBlit(Window -> RPort,Window -> BorderLeft,Window -> BorderTop,RPort,0,0,Width,Height,MINTERM_COPY);
  781.  
  782.                         /* Release the lock on the window layer. */
  783.  
  784.                     UnlockLayerRom(Window -> RPort -> Layer);
  785.  
  786.                         /* Wait for the data to arrive. */
  787.  
  788.                     WaitBlit();
  789.  
  790.                     Locked = FALSE;
  791.  
  792.                         /* Reset the success indicator. */
  793.  
  794.                     Success = FALSE;
  795.  
  796.                         /* Allocate an iff handle. */
  797.  
  798.                     if(Handle = AllocIFF())
  799.                     {
  800.                             /* Open a file for write access. */
  801.  
  802.                         if(Handle -> iff_Stream = Open(Name,MODE_NEWFILE))
  803.                         {
  804.                                 /* Remember that we succeeded
  805.                                  * in creating a new file.
  806.                                  */
  807.  
  808.                             NewFile = TRUE;
  809.  
  810.                                 /* Tell iffparse.library that it's
  811.                                  * a plain AmigaDOS file handle.
  812.                                  */
  813.  
  814.                             InitIFFasDOS(Handle);
  815.  
  816.                                 /* Open the file for writing. */
  817.  
  818.                             if(!(Error = OpenIFF(Handle,IFFF_WRITE)))
  819.                             {
  820.                                     /* Push parent chunk on the
  821.                                      * stack.
  822.                                      */
  823.  
  824.                                 if(!(Error = PushChunk(Handle,ID_ILBM,ID_FORM,IFFSIZE_UNKNOWN)))
  825.                                 {
  826.                                         /* Output all the chunk data. */
  827.  
  828.                                     if(PutANNO(Handle))
  829.                                     {
  830.                                         UBYTE Compression;
  831.  
  832.                                             /* Don't compress the bitmap if
  833.                                              * isn't really worth it.
  834.                                              */
  835.  
  836.                                         if(BitMap -> BytesPerRow > 4)
  837.                                             Compression = cmpByteRun1;
  838.                                         else
  839.                                             Compression = cmpNone;
  840.  
  841.                                         if(PutBMHD(Handle,Window,Compression,Left,Top,Width,Height))
  842.                                         {
  843.                                             if(PutCMAP(Handle,&Window -> WScreen -> ViewPort))
  844.                                             {
  845.                                                 if(PutCAMG(Handle,&Window -> WScreen -> ViewPort))
  846.                                                 {
  847.                                                     if(PutBODY(Handle,BitMap,Compression))
  848.                                                     {
  849.                                                             /* Pop the parent chunk
  850.                                                              * from the stack.
  851.                                                              */
  852.  
  853.                                                         if(!(Error = PopChunk(Handle)))
  854.                                                             Success = TRUE;
  855.                                                     }
  856.                                                     else
  857.                                                         Error = IoErr();
  858.                                                 }
  859.                                                 else
  860.                                                     Error = IoErr();
  861.                                             }
  862.                                             else
  863.                                                 Error = IoErr();
  864.                                         }
  865.                                         else
  866.                                             Error = IoErr();
  867.                                     }
  868.                                     else
  869.                                         Error = IoErr();
  870.                                 }
  871.  
  872.                                     /* Close the iff handle. */
  873.  
  874.                                 CloseIFF(Handle);
  875.                             }
  876.  
  877.                                 /* Close the file. */
  878.  
  879.                             if(!Close(Handle -> iff_Stream))
  880.                             {
  881.                                 Error = IoErr();
  882.  
  883.                                 Success = FALSE;
  884.                             }
  885.                         }
  886.                         else
  887.                             Error = IoErr();
  888.  
  889.                             /* Free the iff handle. */
  890.  
  891.                         FreeIFF(Handle);
  892.                     }
  893.                     else
  894.                         Error = ERR_NO_MEM;
  895.                 }
  896.                 else
  897.                     Error = ERR_NO_MEM;
  898.  
  899.                     /* Free all bitplanes. */
  900.  
  901.                 for(i = 0 ; i < BitMap -> Depth ; i++)
  902.                 {
  903.                     if(BitMap -> Planes[i])
  904.                         FreeRaster(BitMap -> Planes[i],Width,Height);
  905.                 }
  906.  
  907.                     /* Free the bitmap. */
  908.  
  909.                 FreeVecPooled(BitMap);
  910.             }
  911.             else
  912.                 Error = ERR_NO_MEM;
  913.  
  914.                 /* Free the rastport. */
  915.  
  916.             FreeVecPooled(RPort);
  917.         }
  918.         else
  919.             Error = ERR_NO_MEM;
  920.     }
  921.  
  922.         /* Release the window layer in case it is still locked. */
  923.  
  924.     if(Locked)
  925.         UnlockLayerRom(Window -> RPort -> Layer);
  926.  
  927.         /* If successful, clear the `executable' bit. */
  928.  
  929.     if(Success)
  930.     {
  931.         AddProtection(Name,FIBF_EXECUTE);
  932.  
  933.         if(Config -> MiscConfig -> CreateIcons)
  934.             AddIcon(CaptureName,FILETYPE_PICTURE,TRUE);
  935.     }
  936.     else
  937.     {
  938.             /* Delete the remains of the file. */
  939.  
  940.         if(NewFile)
  941.             DeleteFile(Name);
  942.     }
  943.  
  944.         /* Return the result. */
  945.  
  946.     return(Success);
  947. }
  948.